package com.gcb.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.PhoneUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gcb.common.constant.CommonConstants;
import com.gcb.common.constant.CompanyConstants;
import com.gcb.common.core.domain.entity.GcbUser;
import com.gcb.common.core.domain.entity.SysDept;
import com.gcb.common.enums.AuthStatusEnum;
import com.gcb.common.enums.CommonStatusEnum;
import com.gcb.common.enums.CreateTypeEnum;
import com.gcb.common.enums.GcbUserTypeEnum;
import com.gcb.common.exception.ServiceException;
import com.gcb.common.utils.DateUtils;
import com.gcb.common.utils.StringUtils;
import com.gcb.domain.dto.*;
import com.gcb.domain.entity.Company;
import com.gcb.domain.entity.CompanyUser;
import com.gcb.domain.vo.OperateCompanyVO;
import com.gcb.domain.vo.company.CompanyVO;
import com.gcb.domain.vo.company.CompanyPageListVo;
import com.gcb.mapper.CompanyMapper;
import com.gcb.mapper.CompanyUserMapper;
import com.gcb.mapper.GcbUserMapper;
import com.gcb.service.ICompanyService;
import com.gcb.service.ICompanyUserService;
import com.gcb.utils.GcbUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static com.gcb.common.enums.AuthStatusEnum.VERIFIED;
import static com.gcb.common.enums.GcbUserEnum.*;

/**
 * 企业信息Service业务层处理
 *
 * @author seh
 * @since 2024-03-08
 */
@Service
public class CompanyServiceImpl extends ServiceImpl<CompanyMapper, Company> implements ICompanyService {

    @Resource
    private CompanyMapper companyMapper;
    @Resource
    private GcbUserMapper gcbUserMapper;
    @Resource
    private CompanyUserMapper companyUserMapper;
    @Resource
    @Lazy
    private ICompanyUserService companyUserService;

    @Resource
    private GcbUtils gcbUtils;

    @Override
    public Company selectCompanyById(Long id) {
        return companyMapper.selectCompanyById(id);
    }

    @Override
    public List<CompanyPageListVo> selectCompanyList(CompanyListSearchDTO company) {
        List<CompanyPageListVo> voList = companyMapper.selectCompanyManageList(company);

        for (CompanyPageListVo vo : voList) {
            vo.setAuthStatusStr(AuthStatusEnum.getInfo(vo.getAuthStatus()));
            vo.setWaterStatusStr(AuthStatusEnum.getInfo(vo.getWaterStatus()));
            vo.setSignTypeStr(CreateTypeEnum.getInfo(vo.getSignType()));
            vo.setTypeStr(GcbUserTypeEnum.getInfo(vo.getType()));
            vo.setStatusStr(CommonStatusEnum.getInfoByCode(vo.getStatus()));
            //直辖市做特殊处理
            String[] cityArray = Optional.of(vo)
                    .map(CompanyPageListVo::getCityLabel)
                    .orElse("")
                    .split("市");
            if (cityArray.length >= 2 && cityArray[0].equals(cityArray[1])) {
                vo.setCityLabel(cityArray[0] + "市");
            }
            //赋值
            vo.setTypeStr(GcbUserTypeEnum.getInfo(vo.getType()));
        }
        return voList;
    }

    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public int insertCompany(Company company, Long currentUserId) {
        if (StringUtils.isBlank(company.getCompanyAdminPhone())) {
            throw new ServiceException("超级管理员账号不可为空");
        }
        PhoneUtil.isPhone(company.getCompanyAdminPhone());
        //创建超管企业着急管理员账号 如果已存在则新增关联关系
        Long adminUserId = null;
        GcbUser gcbUser = gcbUserMapper.selectOne(new LambdaQueryWrapper<GcbUser>().eq(GcbUser::getMobile, company.getCompanyAdminPhone()));
        if (gcbUser != null) {
            adminUserId = gcbUser.getId();
        } else {
            //新增用户
            GcbUser user = gcbUtils.initUserInfo(company.getCompanyAdminPhone(), CreateTypeEnum.OPERATION, currentUserId);
            int userInsertResult = gcbUserMapper.insert(user);
            if (userInsertResult < 1) {
                throw new ServiceException("超管账户创建失败");
            }
            adminUserId = user.getId();
        }
        company.setSuperAdminId(adminUserId);
        company.setCreateTime(DateUtils.getNowDate());
        //生成企业编号企业的唯一编码，不重复 T+8位数字随机数
        String companyCode = generateCompanyCode();
        company.setCompanyCode(companyCode);
        company.setCompanyName(company.getCompanyNickName());
        company.setLogo(CompanyConstants.COMPANY_DEFAULT_LOGO);
        int companyInsertResult = companyMapper.insert(company);
        if (companyInsertResult < 1) {
            throw new ServiceException("企业创建失败");
        }

        Company companyExists = companyMapper.selectByCompanyCode(companyCode);
        if (Objects.isNull(companyExists)) {
            throw new ServiceException("企业创建失败");
        }
        //新增关系
        CompanyUser companyUser = new CompanyUser();
        companyUser.setCompanyId(company.getId());
        companyUser.setUserId(adminUserId);
        companyUser.setType(COMPANY_SUPER_ADMIN.getCode());
        companyUser.setHireDate(LocalDateTime.now());
        return companyUserMapper.insert(companyUser);
    }

    private String generateCompanyCode() {
        StringBuilder builder = new StringBuilder();
        int randomNum = (int) (Math.random() * 90000000) + 10000000;
        while (companyMapper.selectCompanyByCompanyCode("T" + randomNum) > 0) {
            randomNum = (int) (Math.random() * 90000000) + 10000000;
        }
        builder.append("T").append(randomNum);
        return builder.toString();
    }

    @Override
    public int updateCompany(Company company) {
        // 前端传的是companyName，这里要维护companyNickName
        String companyName = company.getCompanyName();
        String companyNickName = company.getCompanyNickName();
        if (StringUtils.isEmpty(companyNickName)) {
            company.setCompanyNickName(companyName);
        }
        company.setUpdateTime(DateUtils.getNowDate());
        //营业执照唯一
        if (!StringUtils.isBlank(company.getBusinessLicenseNo())) {
            Company licenseInfo = companyMapper.selectCompanyByLicenseNo(company.getBusinessLicenseNo());
            if (licenseInfo != null && !Objects.equals(licenseInfo.getId(), company.getId())) {
                throw new ServiceException("该营业执照已被认证使用");
            }
            company.setAuthStatus(VERIFIED.getCode());
        }
        //船运资质唯一
        if (!StringUtils.isBlank(company.getWaterTransportNo())) {
            Company waterInfo = companyMapper.selectCompanyByWaterTransportNo(company.getWaterTransportNo());
            if (waterInfo != null && !Objects.equals(waterInfo.getId(), company.getId())) {
                throw new ServiceException("该水路运输许可证已被认证使用");
            }
            company.setWaterStatus(VERIFIED.getCode());
        }
        return companyMapper.updateById(company);
    }

    @Override
    public int deleteCompanyByIds(Long[] ids) {
        return companyMapper.deleteCompanyByIds(ids);
    }

    @Override
    public int batchUpdateCompanyStatus(UpdateCompanyStatusDto dto, Long currentUserId) {
        dto.setUpdateBy(currentUserId);
        dto.setUpdateTime(DateUtils.getNowDate());
        return companyMapper.batchUpdateCompanyStatus(dto);
    }

    @Override
    @Transactional
    public int transferCompanySuperAdmin(TransferCompanySuperAdminDto dto, Long currentUserId) {
        Date nowDate = DateUtils.getNowDate();
        Long companyId = dto.getCompanyId();
        Long beforeUserId = dto.getBeforeUserId();
        Long afterUserId = dto.getAfterUserId();

        LambdaQueryWrapper<CompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CompanyUser::getCompanyId, companyId);
        wrapper.eq(CompanyUser::getUserId, beforeUserId);
        //更新原有超级管理员为普通成员
        CompanyUser before = new CompanyUser();
        before.setType(COMMON_USER.getCode());
        before.setUpdateBy(currentUserId);
        companyUserMapper.update(before, wrapper);

        LambdaQueryWrapper<CompanyUser> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(CompanyUser::getCompanyId, companyId);
        wrapper1.eq(CompanyUser::getUserId, afterUserId);
        //更新转移的人员为企业超级管理员
        CompanyUser after = new CompanyUser();
        after.setType(COMPANY_SUPER_ADMIN.getCode());
        after.setUpdateBy(currentUserId);
        companyUserMapper.update(after, wrapper1);

        //更新企业超级管理员绑定id
        Company company = new Company();
        company.setId(dto.getCompanyId());
        company.setSuperAdminId(dto.getAfterUserId());
        company.setUpdateBy(Long.valueOf(currentUserId.toString()));
        company.setUpdateTime(nowDate);
        companyMapper.updateById(company);
        return 1;
    }

    @Override
    public int leaveCompany(CompanyUserSaveDTO dto, Long currentUserId) {
        LambdaQueryWrapper<CompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CompanyUser::getCompanyId, dto.getCompanyId());
        wrapper.eq(CompanyUser::getUserId, dto.getUserId());
        CompanyUser companyUser = companyUserMapper.selectOne(wrapper);
        Validator.validateNotNull(companyUser, "用户不在企业中");
        Validator.validateNotEqual(GcbUserTypeEnum.COMPANY_SUPER_ADMIN.getCode(), companyUser.getType(), "超级管理员不可被移除");

        companyUser.setResignationDate(LocalDateTime.now());
        companyUser.setStatus(DIMISSION.getCode());
        companyUser.setUpdateBy(currentUserId);
        return companyUserMapper.update(companyUser, wrapper);
    }

    @Override
    public int changeCompanyUserRole(CompanyUserSaveDTO dto, Long currentUserId) {
        LambdaQueryWrapper<CompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CompanyUser::getCompanyId, dto.getCompanyId());
        wrapper.eq(CompanyUser::getUserId, dto.getUserId());
        CompanyUser companyUser = companyUserMapper.selectOne(wrapper);
        Validator.validateNotNull(companyUser, "成员不存在");
        Validator.validateNotEqual(GcbUserTypeEnum.COMPANY_SUPER_ADMIN.getCode(), companyUser.getType(), "超级管理员不可更改角色");

        companyUser.setType(dto.getType());
        companyUser.setUpdateBy(currentUserId);
        return companyUserMapper.update(companyUser, wrapper);
    }

    @Override
    public List<OperateCompanyVO> getCompanyListByOperator(Integer status) {
        Company company = new Company();
        company.setStatus(status);
        List<Company> companies = companyMapper.selectCompanyList(company);
        return BeanUtil.copyToList(companies, OperateCompanyVO.class);
    }

    @Override
    public void addCompany(CompanySaveDTO dto) {
        Long userId = dto.getUserId();
        Company company = new Company();
        BeanUtil.copyProperties(dto, company);
        company.setCompanyCode(generateCompanyCode());
        company.setCompanyNickName(company.getCompanyName());
        company.setLogo(CompanyConstants.COMPANY_DEFAULT_LOGO);
        company.setSignType(CreateTypeEnum.USER.getCode());
        company.setAuthStatus(AuthStatusEnum.UN_VERIFIED.getCode());
        company.setCreateTime(new Date());
        company.setUpdateTime(new Date());

        this.save(company);

        CompanyUser companyUser = new CompanyUser();
        companyUser.setCompanyId(company.getId());
        companyUser.setUserId(userId);
        companyUser.setStatus(CommonConstants.CompanyUser.STATE_NORMAL);
        companyUser.setType(GcbUserTypeEnum.COMPANY_SUPER_ADMIN.getCode());
        companyUser.setHireDate(LocalDateTime.now());
        companyUser.setCreateBy(userId);
        companyUser.setUpdateBy(userId);
        companyUserService.save(companyUser);
    }

    @Override
    public SysDept getOperateInfo(String city) {
        return companyMapper.selectDeptByCity(city);
    }

    @Override
    public CompanyVO getDetail(String companyId) {
        Company company = this.getById(companyId);
        return BeanUtil.copyProperties(company, CompanyVO.class);
    }

}
